#include "colortray.h"

ColorTray::ColorTray(QWidget *parent)
    : QWidget(parent)
{
    trayInit();
}

ColorTray::~ColorTray()
{
    clearProfile();
}

void ColorTray::trayInit()
{
    QDir confDir(QDir::toNativeSeparators(QDir::homePath() + "/.config"));
    if (!confDir.exists()) {
        confDir.mkdir(QDir::toNativeSeparators(QDir::homePath() + "/.config"));
    }

    trayReloadAction = new QAction(tr("Reload"),this);
    connect(trayReloadAction,SIGNAL(triggered()),this,SLOT(reloadProfiles()));

    trayClearAction = new QAction(tr("Clear"), this);
    connect(trayClearAction, SIGNAL(triggered()), this, SLOT(clearProfile()));

    trayAboutAction = new QAction(tr("About"), this);
    connect(trayAboutAction, SIGNAL(triggered()), this, SLOT(trayAbout()));

    trayQuitAction = new QAction(tr("Quit"), this);
    connect(trayQuitAction, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()));

    trayMenu = new QMenu(this);
    trayProfileMenu = new QMenu(tr("Load"),this);

    QSettings traySettings(QDir::toNativeSeparators(QDir::homePath() + "/.config/colortray.conf"), QSettings::IniFormat );

    QString monitorProfile0;
    QString monitorProfile1;
    QString monitorProfile2;
    QString monitorProfile3;

    trayMonitor0Menu = new QMenu(tr("Monitor 0"),this);
    trayMonitor1Menu = new QMenu(tr("Monitor 1"),this);
    trayMonitor2Menu = new QMenu(tr("Monitor 2"),this);
    trayMonitor3Menu = new QMenu(tr("Monitor 3"),this);

    trayProfileMenu->addMenu(trayMonitor0Menu);
    trayGenProfiles(0,QDir::homePath()+"/.color/icc");
    trayGenProfiles(0,"/usr/share/color/icc/");
    trayGenProfiles(0,QDir::rootPath()+"WINDOWS/system32/spool/drivers/color");

    trayProfileMenu->addMenu(trayMonitor1Menu);
    trayGenProfiles(1,QDir::homePath()+"/.color/icc");
    trayGenProfiles(1,"/usr/share/color/icc/");
    trayGenProfiles(1,QDir::rootPath()+"WINDOWS/system32/spool/drivers/color");

    trayProfileMenu->addMenu(trayMonitor2Menu);
    trayGenProfiles(2,QDir::homePath()+"/.color/icc");
    trayGenProfiles(2,"/usr/share/color/icc/");
    trayGenProfiles(2,QDir::rootPath()+"WINDOWS/system32/spool/drivers/color");

    trayProfileMenu->addMenu(trayMonitor3Menu);
    trayGenProfiles(3,QDir::homePath()+"/.color/icc");
    trayGenProfiles(3,"/usr/share/color/icc/");
    trayGenProfiles(3,QDir::rootPath()+"WINDOWS/system32/spool/drivers/color");

    traySettings.beginGroup("monitor0");
    if (!traySettings.value("profile").isNull())
    {
        monitorProfile0 = traySettings.value("profile").toString();
        if (!monitorProfile0.isEmpty())
        {
            applyProfile(0,monitorProfile0,0);
        }
    }
    traySettings.endGroup();

    traySettings.beginGroup("monitor1");
    if (!traySettings.value("profile").isNull())
    {
        monitorProfile1 = traySettings.value("profile").toString();
        if (!monitorProfile1.isEmpty())
        {
            applyProfile(1,monitorProfile1,0);
        }
    }
    traySettings.endGroup();

    traySettings.beginGroup("monitor2");
    if (!traySettings.value("profile").isNull())
    {
        monitorProfile2 = traySettings.value("profile").toString();
        if (!monitorProfile2.isEmpty())
        {
            applyProfile(2,monitorProfile2,0);
        }
    }
    traySettings.endGroup();

    traySettings.beginGroup("monitor3");
    if (!traySettings.value("profile").isNull())
    {
        monitorProfile3 = traySettings.value("profile").toString();
        if (!monitorProfile3.isEmpty())
        {
            applyProfile(3,monitorProfile3,0);
        }
    }
    traySettings.endGroup();

    trayMenu->addAction(trayAboutAction);
    trayMenu->addSeparator();
    trayMenu->addMenu(trayProfileMenu);
    trayMenu->addAction(trayReloadAction);
    trayMenu->addAction(trayClearAction);
    trayMenu->addSeparator();
    trayMenu->addAction(trayQuitAction);

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setContextMenu(trayMenu);
    trayIcon->setIcon(QIcon(":/files/tray.png"));
    trayIcon->setToolTip("ColorTray");
    trayIcon->show();
}

void ColorTray::trayAbout()
{
    QMessageBox trayAboutBox;
    trayAboutBox.setWindowIcon(QIcon(":/files/tray.png"));
    trayAboutBox.setIconPixmap(QPixmap(":/files/tray.png"));
    trayAboutBox.setWindowTitle(tr("About")+" ColorTray 0.1");
    trayAboutBox.setText("A simple monitor calibration manager.");
    trayAboutBox.setInformativeText("Copyright (c) 2011 Ole Andre Rodlie\n\nhttp://colortray.googlecode.com");
    trayAboutBox.exec();
}

void ColorTray::trayGenProfiles(int monitor,QString path)
{
    QDir profileDir(QDir::toNativeSeparators(path));
    if (profileDir.exists())
    {
        QStringList profileFilter;
        profileFilter << "*.icc" << "*.icm";
        profileDir.setNameFilters(profileFilter);
        QStringList profiles;
        profiles = profileDir.entryList();
        while (!profiles.isEmpty())
        {
            QString profile = profiles.takeFirst();
            QAction *addProfileAction = new QAction(profileName(path+"/"+profile),this);
            addProfileAction->setData(QString::number(monitor)+","+path+"/"+profile);
            if (monitor == 0)
            {
                trayMonitor0Menu->addAction(addProfileAction);
            }
            if (monitor == 1)
            {
                trayMonitor1Menu->addAction(addProfileAction);
            }
            if (monitor == 2)
            {
                trayMonitor2Menu->addAction(addProfileAction);
            }
            if (monitor == 3)
            {
                trayMonitor3Menu->addAction(addProfileAction);
            }
            connect(addProfileAction,SIGNAL(triggered()),this,SLOT(loadProfile()));
        }
    }
}

void ColorTray::loadProfile()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
    {
        QString profileData = action->data().toString();
        QStringList profileDataSplit = profileData.split(",");
        int profileMonitor = profileDataSplit.takeFirst().toInt();
        QString profilePath = profileDataSplit.takeLast();
        applyProfile(profileMonitor,profilePath,1);
    }
}

QString ColorTray::profileName(QString profile)
{
    QString output;
    QFile verifyProfile(QDir::toNativeSeparators(profile));
    if (verifyProfile.exists())
    {
        cmsHPROFILE lcmsProfile;
        char buffer[500];
        lcmsProfile = cmsOpenProfileFromFile(QDir::toNativeSeparators(profile).toAscii(), "r");
        cmsGetProfileInfoASCII(lcmsProfile, cmsInfoDescription, "en", "US", buffer, 500);
        output=QString::fromAscii(buffer);
        cmsCloseProfile(lcmsProfile);
    }
    verifyProfile.close();
    if (output.isEmpty())
    {
        output = profile;
    }
    return output;
}

void ColorTray::saveProfile(int monitor, QString profile)
{
    QSettings profileConf(QDir::toNativeSeparators(QDir::homePath() + "/.config/colortray.conf"), QSettings::IniFormat );
    profileConf.beginGroup("monitor"+QString::number(monitor));
    profileConf.setValue("profile",profile);
    profileConf.endGroup();
    profileConf.sync();
}

void ColorTray::applyProfile(int monitor, QString profile,int save)
{
    QFile verifyFile(QDir::toNativeSeparators(profile));
    if (verifyFile.exists())
    {
        QString xcalib_exec = "xcalib";
        #ifdef Q_WS_WIN
            xcalib_exec.append(".exe");
        #endif
        QStringList xcalib_args;
        QProcess *xcalib_proc = new QProcess(this);

        xcalib_args << "-s" << QString::number(monitor) << QDir::toNativeSeparators(profile);
        xcalib_proc->start(xcalib_exec,xcalib_args);

        if (save == 1)
        {
            saveProfile(monitor,profile);
        }
    }
    verifyFile.close();
}

void ColorTray::clearProfile()
{
    QString xcalib_exec = "xcalib";
    #ifdef Q_WS_WIN
        xcalib_exec.append(".exe");
    #endif
    QStringList xcalib_args;
    QProcess *xcalib_proc = new QProcess(this);
    xcalib_args << "-clear";
    xcalib_proc->start(xcalib_exec,xcalib_args);
    xcalib_proc->waitForFinished(30000);
}

void ColorTray::reloadProfiles()
{
    QSettings traySettings(QDir::toNativeSeparators(QDir::homePath() + "/.config/colortray.conf"), QSettings::IniFormat );
    traySettings.beginGroup("monitor0");
    if (!traySettings.value("profile").isNull())
    {
        if (!traySettings.value("profile").toString().isEmpty())
        {
            applyProfile(0,traySettings.value("profile").toString(),0);
        }
    }
    traySettings.endGroup();

    traySettings.beginGroup("monitor1");
    if (!traySettings.value("profile").isNull())
    {
        if (!traySettings.value("profile").toString().isEmpty())
        {
            applyProfile(1,traySettings.value("profile").toString(),0);
        }
    }
    traySettings.endGroup();

    traySettings.beginGroup("monitor2");
    if (!traySettings.value("profile").isNull())
    {
        if (!traySettings.value("profile").toString().isEmpty())
        {
            applyProfile(2,traySettings.value("profile").toString(),0);
        }
    }
    traySettings.endGroup();

    traySettings.beginGroup("monitor3");
    if (!traySettings.value("profile").isNull())
    {
        if (!traySettings.value("profile").toString().isEmpty())
        {
            applyProfile(3,traySettings.value("profile").toString(),0);
        }
    }
    traySettings.endGroup();
}
